package com.llyb.tingshu.album.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.llyb.tingshu.album.mapper.AlbumAttributeValueMapper;
import com.llyb.tingshu.album.mapper.AlbumInfoMapper;
import com.llyb.tingshu.album.mapper.AlbumStatMapper;
import com.llyb.tingshu.album.mapper.TrackInfoMapper;
import com.llyb.tingshu.album.service.AlbumAttributeValueService;
import com.llyb.tingshu.album.service.AlbumInfoService;
import com.llyb.tingshu.common.cache.TsCache;
import com.llyb.tingshu.common.constant.RedisConstant;
import com.llyb.tingshu.common.constant.SystemConstant;
import com.llyb.tingshu.common.rabbit.constant.MqConst;
import com.llyb.tingshu.common.rabbit.service.RabbitService;
import com.llyb.tingshu.common.result.Result;
import com.llyb.tingshu.model.album.AlbumAttributeValue;
import com.llyb.tingshu.model.album.AlbumInfo;
import com.llyb.tingshu.model.album.AlbumStat;
import com.llyb.tingshu.model.album.TrackInfo;
import com.llyb.tingshu.query.album.AlbumInfoQuery;
import com.llyb.tingshu.user.client.UserInfoFeignClient;
import com.llyb.tingshu.vo.album.AlbumAttributeValueVo;
import com.llyb.tingshu.vo.album.AlbumInfoVo;
import com.llyb.tingshu.vo.album.AlbumListVo;
import com.llyb.tingshu.vo.album.AlbumStatVo;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RBloomFilter;
import org.redisson.api.RedissonClient;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Random;

@Slf4j
@Service
@SuppressWarnings({"all"})
public class AlbumInfoServiceImpl extends ServiceImpl<AlbumInfoMapper, AlbumInfo> implements AlbumInfoService {

	@Autowired
	private AlbumInfoMapper albumInfoMapper;

	@Autowired
	private AlbumAttributeValueMapper albumAttributeValueMapper;

	@Autowired
	private AlbumStatMapper albumStatMapper;

	@Autowired
	private AlbumAttributeValueService albumAttributeValueService;

	@Autowired
	private RabbitService rabbitService;

	@Autowired
	private RedissonClient redissonClient;

	@Autowired
	private RedisTemplate redisTemplate;

	@Autowired
	private UserInfoFeignClient userInfoFeignClient;

	@Autowired
	private TrackInfoMapper trackInfoMapper;

	@Transactional(rollbackFor = Exception.class)
	@Override
	public Boolean saveAlbumInfo(AlbumInfoVo albumInfoVo, Long userId) {

		// 保存三个表  album_attribute_value,album_info,album_stat

		AlbumInfo albumInfo = new AlbumInfo();

		BeanUtils.copyProperties(albumInfoVo,albumInfo);
		// userId,isfinished,tracksforfree,status 赋值
		albumInfo.setUserId(userId);
		albumInfo.setStatus(SystemConstant.ALBUM_STATUS_PASS);

		if (!SystemConstant.ALBUM_PAY_TYPE_FREE.equals(albumInfoVo.getPayType())) {
			albumInfo.setTracksForFree(5);
		}

		albumInfoMapper.insert(albumInfo);

		List<AlbumAttributeValueVo> albumAttributeValueVoList = albumInfoVo.getAlbumAttributeValueVoList();

		if (!CollectionUtils.isEmpty(albumAttributeValueVoList)) {
			albumAttributeValueVoList.stream().forEach(albumAttributeValueVo -> {
				AlbumAttributeValue albumAttributeValue = new AlbumAttributeValue();

				BeanUtils.copyProperties(albumAttributeValueVo,albumAttributeValue);
				albumAttributeValue.setAlbumId(albumInfo.getId());
				albumAttributeValueMapper.insert(albumAttributeValue);
			});
		}

		this.saveAlbumStat(albumInfo.getId(),SystemConstant.ALBUM_STAT_PLAY);
		this.saveAlbumStat(albumInfo.getId(),SystemConstant.ALBUM_STAT_SUBSCRIBE);
		this.saveAlbumStat(albumInfo.getId(),SystemConstant.ALBUM_STAT_BROWSE);
		this.saveAlbumStat(albumInfo.getId(),SystemConstant.ALBUM_STAT_COMMENT);

		// mq实现专辑的上架
		if ("1".equals(albumInfoVo.getIsOpen())) {
			rabbitService.sendMessage(MqConst.EXCHANGE_ALBUM, MqConst.ROUTING_ALBUM_UPPER, albumInfo.getId());
			// 防止缓存穿透，添加到布隆过滤器
			RBloomFilter<Object> bloomFilter = redissonClient.getBloomFilter(RedisConstant.ALBUM_BLOOM_FILTER);
			bloomFilter.add(albumInfo.getId());
		}


		return true;
	}

	@Override
	public IPage<AlbumListVo> findUserAlbumPage(Page<AlbumListVo> page1, AlbumInfoQuery albumInfoQuery) {
		return albumInfoMapper.selectAlbumInfoList(page1,albumInfoQuery);
	}

	@Override
	@TsCache(prefix = "album:info:")
	public AlbumInfo getAlbumInfo(Long albumId) {

		AlbumInfo albumInfo = albumInfoMapper.selectById(albumId);

		if (null != albumInfo) {
			List<AlbumAttributeValue> albumAttributeValues = albumAttributeValueMapper.selectList(
					new LambdaQueryWrapper<AlbumAttributeValue>().
					eq(AlbumAttributeValue::getAlbumId, albumId));
			albumInfo.setAlbumAttributeValueVoList(albumAttributeValues);
		}

		return albumInfo;
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public Boolean updateAlbumInfo(Long albumId, AlbumInfo albumInfo) {
		// 新增延迟双删 第一步
		String dataKey = "album:info:" + albumId + ":info";
		redisTemplate.delete(dataKey);
		try {
			// 1.更新album_info表
			albumInfo.setId(albumId);
			albumInfoMapper.updateById(albumInfo);

			// 2.删除album_attribute_value表
			albumAttributeValueMapper.delete(new LambdaQueryWrapper<AlbumAttributeValue>().
					eq(AlbumAttributeValue::getAlbumId, albumId));

			// 3.保存album_attribute_value表
			List<AlbumAttributeValue> albumAttributeValueList = albumInfo.getAlbumAttributeValueVoList();
			if (!CollectionUtils.isEmpty(albumAttributeValueList)) {
				albumAttributeValueList.stream().
						forEach(albumAttributeValue -> {albumAttributeValue.setAlbumId(albumId);});
				albumAttributeValueService.saveBatch(albumAttributeValueList);
			}

			// mq实现专辑的上架
			if ("1".equals(albumInfo.getIsOpen())) {
				rabbitService.sendMessage(MqConst.EXCHANGE_ALBUM, MqConst.ROUTING_ALBUM_UPPER, albumInfo.getId());
				// 添加到布隆过滤器
				RBloomFilter<Object> bloomFilter = redissonClient.getBloomFilter(RedisConstant.ALBUM_BLOOM_FILTER);
				bloomFilter.add(albumId);
			}else {
				rabbitService.sendMessage(MqConst.EXCHANGE_ALBUM, MqConst.ROUTING_ALBUM_LOWER, albumInfo.getId());
			}
		} catch (Exception e) {
			log.error("更新专辑信息失败：{}",e.getMessage());
			throw new RuntimeException(e);
		}
		// 延迟时间（一般大于上述业务的时间） 第二步
		try {
			Thread.sleep(200);
		} catch (InterruptedException e) {
			throw new RuntimeException(e);
		}
		// 新增延迟双删  第三步
		redisTemplate.delete(dataKey);
		return true;
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public Boolean removeAlbumInfo(Long albumId) {
		 albumAttributeValueService.remove(
				new LambdaQueryWrapper<AlbumAttributeValue>().
						eq(AlbumAttributeValue::getAlbumId, albumId));
		albumStatMapper.delete(
				new LambdaQueryWrapper<AlbumStat>().
						eq(AlbumStat::getAlbumId, albumId));
		// 删除专辑信息,从es中移除
		rabbitService.sendMessage(MqConst.EXCHANGE_ALBUM, MqConst.ROUTING_ALBUM_LOWER, albumId);
		return albumInfoMapper.deleteById(albumId) > 0;
	}

	@Override
	public List<AlbumInfo> findUserAllAlbumList(Long userId) {
		Page<AlbumInfo> page = new Page<>(1, 100);

		Page<AlbumInfo> albumInfoPage = albumInfoMapper.selectPage(page, new LambdaQueryWrapper<AlbumInfo>().
				select(AlbumInfo::getId, AlbumInfo::getAlbumTitle).
				eq(AlbumInfo::getUserId, userId).
				orderByDesc(AlbumInfo::getId));

		return albumInfoPage.getRecords();
	}

	/**
	 * 根据专辑id获取专辑统计信息
	 * @param albumId
	 * @return
	 */
	@Override
	@TsCache(prefix = "album:stat:")
	public AlbumStatVo getAlbumStat(Long albumId) {
		AlbumStatVo albumStatVo = albumStatMapper.selectStatsById(albumId);
		return albumStatVo;
	}


	public void saveAlbumStat(Long id, String albumStatComment) {
		AlbumStat albumStat = new AlbumStat();
		albumStat.setAlbumId(id);
		albumStat.setStatType(albumStatComment);
		albumStat.setStatNum(new Random().nextInt(10000));
		albumStatMapper.insert(albumStat);
	}
}
